// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>

#include <string>
#include <tuple>
#include <vector>

#include "base/base_switches.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "media/base/media_switches.h"
#include "media/base/test_data_util.h"
#include "media/media_buildflags.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/widevine/cdm/buildflags.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#include "chrome/browser/media/library_cdm_test_helper.h"
#include "media/cdm/cdm_paths.h"
#endif

#if BUILDFLAG(IS_ANDROID)
#error This file needs to be updated to run on Android.
#endif

namespace {

const char kClearKey[] = "org.w3.clearkey";
const char kExternalClearKey[] = "org.chromium.externalclearkey";
const char kWidevine[] = "com.widevine.alpha";
const char kWidevineExperiment[] = "com.widevine.alpha.experiment";

const char kAudioWebMMimeType[] = "audio/webm";
const char kVideoWebMMimeType[] = "video/webm";
const char kAudioMP4MimeType[] = "audio/mp4";
const char kVideoMP4MimeType[] = "video/mp4";

// These are the expected titles set by checkKeySystemWithMediaMimeType()
// in test_key_system_instantiation.html. Other titles are possible, but
// they are unexpected and will be logged with the failure. kUnsupportedResult
// is the actual message generated by navigator.requestMediaKeySystemAccess(),
// and will need to be updated if that code is modified.
const char kSuccessResult[] = "success";
const char16_t kSuccessResult16[] = u"success";
const char kUnsupportedResult[] =
    "Unsupported keySystem or supportedConfigurations.";
const char16_t kUnsupportedResult16[] =
    u"Unsupported keySystem or supportedConfigurations.";
const char16_t kUnexpectedResult16[] = u"unexpected result";

#define EXPECT_SUCCESS(test) EXPECT_EQ(kSuccessResult, test)
#define EXPECT_UNSUPPORTED(test) EXPECT_EQ(kUnsupportedResult, test)

// Any support is acceptable. This can be used around new CDM check-in time
// where test expectations can change based on the new CDM's capability.
// For any usage of EXPECT_ANY, add a TODO explaining the plan to fix it.
#define EXPECT_ANY(test) std::ignore = test

#if BUILDFLAG(ENABLE_AV1_DECODER)
#define EXPECT_AV1 EXPECT_SUCCESS
#else
#define EXPECT_AV1 EXPECT_UNSUPPORTED
#endif

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#define EXPECT_PROPRIETARY EXPECT_SUCCESS
#else
#define EXPECT_PROPRIETARY EXPECT_UNSUPPORTED
#endif

// Expectations for External Clear Key.
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#define EXPECT_ECK EXPECT_SUCCESS
#define EXPECT_ECK_AV1 EXPECT_AV1
#define EXPECT_ECK_PROPRIETARY EXPECT_PROPRIETARY
#else
#define EXPECT_ECK EXPECT_UNSUPPORTED
#define EXPECT_ECK_AV1 EXPECT_UNSUPPORTED
#define EXPECT_ECK_PROPRIETARY EXPECT_UNSUPPORTED
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

// Expectations for Widevine.
#if BUILDFLAG(BUNDLE_WIDEVINE_CDM)
#define EXPECT_WV EXPECT_SUCCESS
#define EXPECT_WV_AV1 EXPECT_AV1
#define EXPECT_WV_PROPRIETARY EXPECT_PROPRIETARY
#else
#define EXPECT_WV EXPECT_UNSUPPORTED
#define EXPECT_WV_AV1 EXPECT_UNSUPPORTED
#define EXPECT_WV_PROPRIETARY EXPECT_UNSUPPORTED
#endif  // BUILDFLAG(BUNDLE_WIDEVINE_CDM)

}  // namespace

class EncryptedMediaSupportedTypesTest : public InProcessBrowserTest {
 protected:
  EncryptedMediaSupportedTypesTest() {
    // TODO(crbug.com/1243903): WhatsNewUI might be causing timeouts.
    disabled_features_.push_back(features::kChromeWhatsNewUI);

    audio_webm_codecs_.push_back("vorbis");

    video_webm_codecs_.push_back("vp8");
    video_webm_codecs_.push_back("vp8.0");
    video_webm_codecs_.push_back("vp9");    // Legacy VP9 only supported in WebM
    video_webm_codecs_.push_back("vp9.0");  // Legacy VP9 only supported in WebM

    audio_mp4_codecs_.push_back("mp4a.40.2");

    audio_mp4_flac_codecs_.push_back("flac");

    video_mp4_codecs_.push_back("avc1.42001E");  // Baseline profile.
    video_mp4_codecs_.push_back("avc1.4D000C");  // Main profile.
    video_mp4_codecs_.push_back("avc3.64001F");  // High profile.

    video_mp4_hi10p_codecs_.push_back("avc1.6E001E");  // Hi10P profile

    video_mp4_hevc_codecs_.push_back("hvc1.1.6.L93.B0");
    video_mp4_hevc_codecs_.push_back("hev1.1.6.L93.B0");

    // Opus is supported in both MP4 and WebM.
    opus_codecs_.push_back("opus");

    // New multi-part VP9 codecs are allowed in both MP4 and WebM.
    // For vp9 codec string format, see https://www.webmproject.org/vp9/mp4/
    vp9_profile0_codecs_.push_back("vp09.00.10.08");

    // VP9 profile 2 is supported in WebM/MP4 with ClearKey/ExternalClearKey.
    // TODO(crbug.com/707128): Add support in Widevine CDM.
    vp9_profile2_codecs_.push_back("vp09.02.10.10");

    // AV1 codec string: https://aomediacodec.github.io/av1-isobmff/#codecsparam
    av1_codecs_.push_back("av01.0.04M.08");        // 8 bit
    av1_codecs_.push_back("av01.0.00M.10.0.112");  // 10 bit

    // Extended codecs are used, so make sure generic ones fail. These will be
    // tested against all init data types as they should always fail to be
    // supported.
    invalid_codecs_.push_back("avc1");
    invalid_codecs_.push_back("avc1.");
    invalid_codecs_.push_back("avc3");

    // Other invalid codecs.
    invalid_codecs_.push_back("vp8.1");
    invalid_codecs_.push_back("mp4a");
    invalid_codecs_.push_back("avc2");
    invalid_codecs_.push_back("foo");

    // We only support proper long-form HEVC codec ids.
    invalid_codecs_.push_back("hev1");
    invalid_codecs_.push_back("hev1.");
    invalid_codecs_.push_back("hvc1");
    invalid_codecs_.push_back("hvc1.");

    // Profile 1 and 3 are not supported by EME. See https://crbug.com/898298.
    invalid_codecs_.push_back("vp09.01.10.08");
    invalid_codecs_.push_back("vp09.03.10.10");
  }

  typedef std::vector<std::string> CodecVector;

  const CodecVector& no_codecs() const { return no_codecs_; }
  const CodecVector& audio_webm_codecs() const { return audio_webm_codecs_; }
  const CodecVector& video_webm_codecs() const { return video_webm_codecs_; }
  const CodecVector& audio_mp4_codecs() const { return audio_mp4_codecs_; }
  const CodecVector& audio_mp4_flac_codecs() const {
    return audio_mp4_flac_codecs_;
  }
  const CodecVector& video_mp4_codecs() const { return video_mp4_codecs_; }
  const CodecVector& video_mp4_hi10p_codecs() const {
    return video_mp4_hi10p_codecs_;
  }
  const CodecVector& video_mp4_hevc_codecs() const {
    return video_mp4_hevc_codecs_;
  }

  const CodecVector& opus_codecs() const { return opus_codecs_; }
  const CodecVector& vp9_profile0_codecs() const {
    return vp9_profile0_codecs_;
  }
  const CodecVector& vp9_profile2_codecs() const {
    return vp9_profile2_codecs_;
  }
  const CodecVector& av1_codecs() const { return av1_codecs_; }
  const CodecVector& invalid_codecs() const { return invalid_codecs_; }

  void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
    base::CommandLine default_command_line(base::CommandLine::NO_PROGRAM);
    InProcessBrowserTest::SetUpDefaultCommandLine(&default_command_line);
    test_launcher_utils::RemoveCommandLineSwitch(
        default_command_line, switches::kDisableComponentUpdate, command_line);
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

    feature_list_.InitWithFeatures(enabled_features_, disabled_features_);
  }

  void SetUpOnMainThread() override {
    // Load the test page needed so that checkKeySystemWithMediaMimeType()
    // is available.
    net::EmbeddedTestServer* http_test_server = embedded_test_server();
    http_test_server->ServeFilesFromSourceDirectory(media::GetTestDataPath());
    CHECK(http_test_server->Start());
    GURL gurl = http_test_server->GetURL("/test_key_system_instantiation.html");
    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
  }

  // Create a valid JavaScript string for the content type. Format is
  // |mime_type|; codecs="|codec|", where codecs= is omitted if there
  // is no codec.
  static std::string MakeContentType(const std::string& mime_type,
                                     const std::string& codec) {
    std::string content_type(mime_type);
    if (!codec.empty())
      content_type += base::StringPrintf("; codecs=\"%s\"", codec.c_str());
    return content_type;
  }

  // Format: {contentType: |content_type|, encryptionScheme:
  // |encryption_scheme|, robustness: |robustness|}. encryptionScheme and
  // robustness will not be included if |encryption_scheme| or |robustness|
  // is null, respectively.
  static std::string MakeMediaCapability(const std::string& content_type,
                                         const char* robustness,
                                         const char* encryption_scheme) {
    std::string capability =
        base::StringPrintf("{contentType: '%s'", content_type.c_str());
    if (encryption_scheme) {
      base::StringAppendF(&capability, ", encryptionScheme: '%s'",
                          encryption_scheme);
    }
    if (robustness) {
      base::StringAppendF(&capability, ", robustness: '%s'", robustness);
    }
    base::StringAppendF(&capability, "}");
    return capability;
  }

  static std::string MakeMediaCapabilities(const std::string& mime_type,
                                           const CodecVector& codecs,
                                           const char* robustness,
                                           const char* encryption_scheme) {
    std::string capabilities("[");
    if (codecs.empty()) {
      capabilities +=
          MakeMediaCapability(MakeContentType(mime_type, std::string()),
                              robustness, encryption_scheme);
    } else {
      for (auto codec : codecs) {
        capabilities += MakeMediaCapability(MakeContentType(mime_type, codec),
                                            robustness, encryption_scheme) +
                        ",";
      }
      // Remove trailing comma.
      capabilities.erase(capabilities.length() - 1);
    }
    capabilities += ("]");
    return capabilities;
  }

  static std::string ExecuteCommand(content::WebContents* contents,
                                    const std::string& command) {
    content::TitleWatcher title_watcher(contents, kSuccessResult16);
    title_watcher.AlsoWaitForTitle(kUnsupportedResult16);
    title_watcher.AlsoWaitForTitle(kUnexpectedResult16);
    EXPECT_TRUE(content::ExecuteScript(contents, command));
    std::u16string result = title_watcher.WaitAndGetTitle();
    return base::UTF16ToASCII(result);
  }

  enum class SessionType {
    kTemporary,          // Temporary session
    kPersistentLicense,  // Persistent license session
  };

  std::string GetSessionTypeString(SessionType session_type) {
    switch (session_type) {
      case SessionType::kTemporary:
        return "temporary";
      case SessionType::kPersistentLicense:
        return "persistent-license";
    }

    NOTREACHED();
    return "";
  }

  std::string IsSupportedByKeySystem(
      const std::string& key_system,
      const std::string& mime_type,
      const CodecVector& codecs,
      SessionType session_type = SessionType::kTemporary,
      const char* robustness = nullptr,
      const char* encryption_scheme = nullptr) {
    // Choose the appropriate init data type for the sub type.
    size_t pos = mime_type.find('/');
    DCHECK(pos > 0);
    std::string sub_type(mime_type.substr(pos + 1));
    std::string init_data_type;
    if (sub_type == "mp4") {
      init_data_type = "cenc";
    } else {
      DCHECK(sub_type == "webm");
      init_data_type = "webm";
    }

    bool is_audio = mime_type.compare(0, 5, "audio") == 0;
    DCHECK(is_audio || mime_type.compare(0, 5, "video") == 0);
    auto capabilities =
        MakeMediaCapabilities(mime_type, codecs, robustness, encryption_scheme);
    auto audio_capabilities = is_audio ? capabilities : "null";
    auto video_capabilities = !is_audio ? capabilities : "null";
    auto session_type_string = GetSessionTypeString(session_type);

    std::string command = base::StringPrintf(
        "checkKeySystemWithMediaMimeType('%s', '%s', %s, %s, '%s')",
        key_system.c_str(), init_data_type.c_str(), audio_capabilities.c_str(),
        video_capabilities.c_str(), session_type_string.c_str());
    DVLOG(1) << "command: " << command;

    auto result = ExecuteCommand(
        browser()->tab_strip_model()->GetActiveWebContents(), command);
    DVLOG(1) << "result: " << result;

    return result;
  }

  std::string IsSessionTypeSupported(const std::string& key_system,
                                     SessionType session_type) {
    return IsSupportedByKeySystem(key_system, kVideoWebMMimeType,
                                  video_webm_codecs(), session_type);
  }

  std::string IsAudioRobustnessSupported(const std::string& key_system,
                                         const char* robustness) {
    return IsSupportedByKeySystem(key_system, kAudioWebMMimeType,
                                  audio_webm_codecs(), SessionType::kTemporary,
                                  robustness);
  }

  std::string IsVideoRobustnessSupported(const std::string& key_system,
                                         const char* robustness) {
    return IsSupportedByKeySystem(key_system, kVideoWebMMimeType,
                                  video_webm_codecs(), SessionType::kTemporary,
                                  robustness);
  }

  std::string IsVideoMp4RobustnessSupported(const std::string& key_system,
                                            const char* robustness) {
    return IsSupportedByKeySystem(key_system, kVideoMP4MimeType,
                                  video_mp4_codecs(), SessionType::kTemporary,
                                  robustness);
  }

  std::string IsVideoMp4HevcRobustnessSupported(const std::string& key_system,
                                                const char* robustness) {
    return IsSupportedByKeySystem(key_system, kVideoMP4MimeType,
                                  video_mp4_hevc_codecs(),
                                  SessionType::kTemporary, robustness);
  }

  std::string IsAudioMp4RobustnessSupported(const std::string& key_system,
                                            const char* robustness) {
    return IsSupportedByKeySystem(key_system, kAudioMP4MimeType,
                                  audio_mp4_codecs(), SessionType::kTemporary,
                                  robustness);
  }

  std::string IsAudioEncryptionSchemeSupported(
      const std::string& key_system,
      const char* encryption_scheme,
      const char* robustness = nullptr) {
    return IsSupportedByKeySystem(key_system, kAudioWebMMimeType,
                                  audio_webm_codecs(), SessionType::kTemporary,
                                  robustness, encryption_scheme);
  }

  std::string IsVideoEncryptionSchemeSupported(
      const std::string& key_system,
      const char* encryption_scheme,
      const char* robustness = nullptr) {
    return IsSupportedByKeySystem(key_system, kVideoWebMMimeType,
                                  video_webm_codecs(), SessionType::kTemporary,
                                  robustness, encryption_scheme);
  }

 protected:
  // Features to enable or disable for the test. Must be updated in the test
  // constructor (before SetUpDefaultCommandLine()) to take effect.
  std::vector<base::Feature> enabled_features_;
  std::vector<base::Feature> disabled_features_;
  base::test::ScopedFeatureList feature_list_;

 private:
  const CodecVector no_codecs_;
  CodecVector audio_webm_codecs_;
  CodecVector video_webm_codecs_;
  CodecVector audio_mp4_codecs_;
  CodecVector audio_mp4_flac_codecs_;
  CodecVector video_mp4_codecs_;
  CodecVector video_mp4_hi10p_codecs_;
  CodecVector video_mp4_hevc_codecs_;
  CodecVector opus_codecs_;
  CodecVector vp9_profile0_codecs_;
  CodecVector vp9_profile2_codecs_;
  CodecVector av1_codecs_;
  CodecVector invalid_codecs_;
};

// For ClearKey, nothing additional is required.
class EncryptedMediaSupportedTypesClearKeyTest
    : public EncryptedMediaSupportedTypesTest {};

// For ExternalClearKey tests, ensure that the ClearKey adapter is loaded.
class EncryptedMediaSupportedTypesExternalClearKeyTest
    : public EncryptedMediaSupportedTypesTest {
 public:
  EncryptedMediaSupportedTypesExternalClearKeyTest(
      const EncryptedMediaSupportedTypesExternalClearKeyTest&) = delete;
  EncryptedMediaSupportedTypesExternalClearKeyTest& operator=(
      const EncryptedMediaSupportedTypesExternalClearKeyTest&) = delete;

 protected:
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
  EncryptedMediaSupportedTypesExternalClearKeyTest() {
    enabled_features_.push_back(media::kExternalClearKeyForTesting);
  }

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesTest::SetUpCommandLine(command_line);
    RegisterClearKeyCdm(command_line);
  }
#else
  EncryptedMediaSupportedTypesExternalClearKeyTest() = default;
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

  ~EncryptedMediaSupportedTypesExternalClearKeyTest() override = default;
};

// By default, the External Clear Key (ECK) key system is not supported even if
// present. This test case tests this behavior by not enabling
// kExternalClearKeyForTesting. Even registering the Clear Key CDM does not
// enable the ECK key system support.
class EncryptedMediaSupportedTypesExternalClearKeyNotEnabledTest
    : public EncryptedMediaSupportedTypesTest {
 protected:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesTest::SetUpCommandLine(command_line);
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
    RegisterClearKeyCdm(command_line);
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
  }
};

class EncryptedMediaSupportedTypesWidevineTest
    : public EncryptedMediaSupportedTypesTest {
 public:
  EncryptedMediaSupportedTypesWidevineTest(
      const EncryptedMediaSupportedTypesWidevineTest&) = delete;
  EncryptedMediaSupportedTypesWidevineTest& operator=(
      const EncryptedMediaSupportedTypesWidevineTest&) = delete;

 protected:
  EncryptedMediaSupportedTypesWidevineTest() = default;

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesTest::SetUpCommandLine(command_line);
    // Persistent license is supported on ChromeOS when protected media
    // identifier is allowed which involves a user action. Use this switch to
    // always allow the identifier for testing purpose. Note that the test page
    // is hosted on "127.0.0.1". See net::EmbeddedTestServer for details.
    command_line->AppendSwitchASCII(
        switches::kUnsafelyAllowProtectedMediaIdentifierForDomain, "127.0.0.1");
  }
};

class EncryptedMediaSupportedTypesWidevineHwSecureTest
    : public EncryptedMediaSupportedTypesWidevineTest {
 public:
  EncryptedMediaSupportedTypesWidevineHwSecureTest(
      const EncryptedMediaSupportedTypesWidevineHwSecureTest&) = delete;
  EncryptedMediaSupportedTypesWidevineHwSecureTest& operator=(
      const EncryptedMediaSupportedTypesWidevineHwSecureTest&) = delete;

 protected:
  EncryptedMediaSupportedTypesWidevineHwSecureTest() {
    enabled_features_.push_back(media::kHardwareSecureDecryption);
  }

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesWidevineTest::SetUpCommandLine(command_line);
    // Pretend that we support hardware secure decryption for vp8 and vp9, but
    // not for avc1. This will also pretend that there is support for vorbis
    // audio.
    command_line->AppendSwitchASCII(
        switches::kOverrideHardwareSecureCodecsForTesting, "vp8,vp9,vorbis");
  }
};

class EncryptedMediaSupportedTypesWidevineHwSecureExperimentTest
    : public EncryptedMediaSupportedTypesWidevineTest {
 protected:
  EncryptedMediaSupportedTypesWidevineHwSecureExperimentTest() {
    enabled_features_.push_back(media::kHardwareSecureDecryptionExperiment);
  }

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesWidevineTest::SetUpCommandLine(command_line);
    // Pretend that we support hardware secure decryption for vp8 and vp9, but
    // not for avc1. This will also pretend that there is support for vorbis
    // audio.
    command_line->AppendSwitchASCII(
        switches::kOverrideHardwareSecureCodecsForTesting, "vp8,vp9,vorbis");
  }
};

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
// Registers ClearKey CDM with the wrong path (filename).
class EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest
    : public EncryptedMediaSupportedTypesTest {
 public:
  EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest(
      const EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest&) =
      delete;
  EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest& operator=(
      const EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest&) =
      delete;

 protected:
  EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest() {
    enabled_features_.push_back(media::kExternalClearKeyForTesting);
  }

  ~EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest()
      override {}

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesTest::SetUpCommandLine(command_line);
    RegisterClearKeyCdm(command_line, true /* use_wrong_cdm_path */);
  }
};
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Basic) {
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        video_webm_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                        audio_webm_codecs()));
  EXPECT_SUCCESS(
      IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType, opus_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                        audio_mp4_flac_codecs()));
  EXPECT_PROPRIETARY(
      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, video_mp4_codecs()));
  EXPECT_PROPRIETARY(
      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, audio_mp4_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, NoCodecs) {
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType, no_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType, no_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, no_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, no_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest,
                       InvalidKeySystems) {
  // Case sensitive.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "org.w3.ClEaRkEy", kVideoWebMMimeType, video_webm_codecs()));

  // Prefixed Clear Key key system.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "webkit-org.w3.clearkey", kVideoWebMMimeType, video_webm_codecs()));

  // TLDs are not allowed.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("org.", kVideoWebMMimeType, video_webm_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("org", kVideoWebMMimeType, video_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("org.w3.", kVideoWebMMimeType,
                                            video_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("org.w3", kVideoWebMMimeType,
                                            video_webm_codecs()));

  // Incomplete.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "org.w3.clearke", kVideoWebMMimeType, video_webm_codecs()));

  // Extra character.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "org.w3.clearkeyz", kVideoWebMMimeType, video_webm_codecs()));

  // There are no child key systems for Clear Key.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "org.w3.clearkey.foo", kVideoWebMMimeType, video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Video_WebM) {
  // Valid video types.
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        video_webm_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        vp9_profile0_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        vp9_profile2_codecs()));
  EXPECT_AV1(
      IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType, av1_codecs()));

  // Non-video WebM codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                            audio_webm_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType, opus_codecs()));

  // Invalid or non-Webm video codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                            audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                            video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                            video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Audio_WebM) {
  // Valid audio types.
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                        audio_webm_codecs()));
  EXPECT_SUCCESS(
      IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType, opus_codecs()));

  // Non-audio WebM codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                            video_webm_codecs()));

  // Invalid or Non-Webm codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                            audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                            audio_mp4_flac_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                            video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                            video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Video_MP4) {
  // Valid video types.
  EXPECT_PROPRIETARY(
      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                            video_mp4_hevc_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                        vp9_profile0_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                        vp9_profile2_codecs()));
  EXPECT_AV1(
      IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType, av1_codecs()));

// High 10-bit Profile is supported when using ClearKey if it is supported for
// clear content on this platform.
#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  EXPECT_PROPRIETARY(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                            video_mp4_hi10p_codecs()));
#else
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                            video_mp4_hi10p_codecs()));
#endif

  // Non-video MP4 codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, opus_codecs()));

  // Invalid or non-MP4 codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                            audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType,
                                            video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Audio_MP4) {
  // Valid audio types.
  EXPECT_PROPRIETARY(
      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, audio_mp4_codecs()));
  EXPECT_SUCCESS(
      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, opus_codecs()));
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                        audio_mp4_flac_codecs()));

  // Non-audio MP4 codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                            video_mp4_hevc_codecs()));

  // Invalid or non-MP4 codec.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                            audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                            video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, SessionType) {
  // Temporary session always supported.
  EXPECT_SUCCESS(IsSessionTypeSupported(kClearKey, SessionType::kTemporary));

  // Persistent sessions not supported by Clear Key key system.
  EXPECT_UNSUPPORTED(
      IsSessionTypeSupported(kClearKey, SessionType::kPersistentLicense));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Robustness) {
  // External Clear Key doesn't require a robustness string.
  EXPECT_SUCCESS(IsVideoRobustnessSupported(kClearKey, nullptr));
  EXPECT_SUCCESS(IsVideoRobustnessSupported(kClearKey, ""));
  EXPECT_SUCCESS(IsAudioRobustnessSupported(kClearKey, nullptr));
  EXPECT_SUCCESS(IsAudioRobustnessSupported(kClearKey, ""));

  // Non-empty robustness string will be rejected, including valid Widevine
  // robustness strings.
  EXPECT_UNSUPPORTED(IsVideoRobustnessSupported(kClearKey, "Invalid String"));
  EXPECT_UNSUPPORTED(IsVideoRobustnessSupported(kClearKey, "SW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kClearKey, "Invalid String"));
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kClearKey, "SW_SECURE_CRYPTO"));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest,
                       EncryptionScheme) {
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kClearKey, nullptr));
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kClearKey, "cenc"));
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kClearKey, "cbcs"));
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kClearKey, "cbcs-1-9"));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kClearKey, nullptr));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kClearKey, "cenc"));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kClearKey, "cbcs"));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kClearKey, "cbcs-1-9"));

  // Invalid encryption schemes will be rejected.
  EXPECT_UNSUPPORTED(IsAudioEncryptionSchemeSupported(kClearKey, "Invalid"));
  EXPECT_UNSUPPORTED(IsVideoEncryptionSchemeSupported(kClearKey, "Invalid"));
  EXPECT_UNSUPPORTED(IsAudioEncryptionSchemeSupported(kClearKey, ""));
  EXPECT_UNSUPPORTED(IsVideoEncryptionSchemeSupported(kClearKey, ""));
}

//
// External Clear Key
//

// When BUILDFLAG(ENABLE_LIBRARY_CDMS), this also tests the library CDM check.
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Basic) {
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kVideoWebMMimeType,
                                    video_webm_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
                                    audio_webm_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
                                    opus_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioMP4MimeType,
                                    audio_mp4_flac_codecs()));
  EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_codecs()));
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
  EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_hevc_codecs()));
#else
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_hevc_codecs()));
#endif
  EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, audio_mp4_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       NoCodecs) {
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
                                            kVideoWebMMimeType, no_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
                                            kAudioWebMMimeType, no_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
                                            kVideoMP4MimeType, no_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
                                            kAudioMP4MimeType, no_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       InvalidKeySystems) {
  // Case sensitive.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("org.chromium.ExTeRnAlClEaRkEy",
                                            kVideoWebMMimeType,
                                            video_webm_codecs()));

  // TLDs are not allowed.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("org.", kVideoWebMMimeType, video_webm_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("org", kVideoWebMMimeType, video_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("org.chromium", kVideoWebMMimeType,
                                            video_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("org.chromium.", kVideoWebMMimeType,
                                            video_webm_codecs()));

  // Incomplete.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "org.chromium.externalclearke", kVideoWebMMimeType, video_webm_codecs()));

  // Extra character.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("org.chromium.externalclearkeyz",
                                            kVideoWebMMimeType,
                                            video_webm_codecs()));

  // Child key systems for External Clear Key are generally supported except
  // for the special one explicitly marked as "invalid". See
  // ExternalClearKeyProperties.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("org.chromium.externalclearkey.invalid",
                             kVideoWebMMimeType, video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Video_WebM) {
  // Valid video types.
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kVideoWebMMimeType,
                                    video_webm_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kVideoWebMMimeType,
                                    vp9_profile0_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kVideoWebMMimeType,
                                    vp9_profile2_codecs()));
  EXPECT_ECK_AV1(IsSupportedByKeySystem(kExternalClearKey, kVideoWebMMimeType,
                                        av1_codecs()));

  // Non-video WebM codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
                                            kVideoWebMMimeType, opus_codecs()));

  // Invalid or non-Webm codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Audio_WebM) {
  // Valid audio types.
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
                                    audio_webm_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
                                    opus_codecs()));

  // Non-audio WebM codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioWebMMimeType, video_webm_codecs()));

  // Invalid or non-Webm codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioWebMMimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioWebMMimeType, audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioWebMMimeType, audio_mp4_flac_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioWebMMimeType, video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioWebMMimeType, video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Video_MP4) {
  // Valid video types.
  EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_codecs()));
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
  EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_hevc_codecs()));
#else
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_hevc_codecs()));
#endif
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kVideoMP4MimeType,
                                    vp9_profile0_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kVideoMP4MimeType,
                                    vp9_profile2_codecs()));
  EXPECT_ECK_AV1(IsSupportedByKeySystem(kExternalClearKey, kVideoWebMMimeType,
                                        av1_codecs()));

  // High 10-bit Profile is not supported when using ExternalClearKey.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_mp4_hi10p_codecs()));

  // Non-video MP4 codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
                                            kVideoMP4MimeType, opus_codecs()));

  // Invalid or non-MP4 codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoMP4MimeType, video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Audio_MP4) {
  // Valid audio types.
  EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, audio_mp4_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioMP4MimeType,
                                    opus_codecs()));
  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioMP4MimeType,
                                    audio_mp4_flac_codecs()));

  // Non-audio MP4 codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, video_mp4_hevc_codecs()));

  // Invalid or Non-MP4 codec.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kAudioMP4MimeType, video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       SessionType) {
  // Temporary session always supported.
  EXPECT_SUCCESS(
      IsSessionTypeSupported(kExternalClearKey, SessionType::kTemporary));

  // Persistent sessions always supported by External Clear Key.
  EXPECT_SUCCESS(IsSessionTypeSupported(kExternalClearKey,
                                        SessionType::kPersistentLicense));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Robustness) {
  // External Clear Key doesn't require a robustness string.
  EXPECT_SUCCESS(IsVideoRobustnessSupported(kExternalClearKey, nullptr));
  EXPECT_SUCCESS(IsVideoRobustnessSupported(kExternalClearKey, ""));
  EXPECT_SUCCESS(IsAudioRobustnessSupported(kExternalClearKey, nullptr));
  EXPECT_SUCCESS(IsAudioRobustnessSupported(kExternalClearKey, ""));

  // Non-empty robustness string will be rejected, including valid Widevine
  // robustness strings.
  EXPECT_UNSUPPORTED(
      IsVideoRobustnessSupported(kExternalClearKey, "Invalid String"));
  EXPECT_UNSUPPORTED(
      IsVideoRobustnessSupported(kExternalClearKey, "SW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsAudioRobustnessSupported(kExternalClearKey, "Invalid String"));
  EXPECT_UNSUPPORTED(
      IsAudioRobustnessSupported(kExternalClearKey, "SW_SECURE_CRYPTO"));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       EncryptionScheme) {
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kExternalClearKey, nullptr));
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kExternalClearKey, "cenc"));
  EXPECT_SUCCESS(IsAudioEncryptionSchemeSupported(kExternalClearKey, "cbcs"));
  EXPECT_SUCCESS(
      IsAudioEncryptionSchemeSupported(kExternalClearKey, "cbcs-1-9"));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kExternalClearKey, nullptr));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kExternalClearKey, "cenc"));
  EXPECT_SUCCESS(IsVideoEncryptionSchemeSupported(kExternalClearKey, "cbcs"));
  EXPECT_SUCCESS(
      IsVideoEncryptionSchemeSupported(kExternalClearKey, "cbcs-1-9"));

  // Invalid encryption schemes will be rejected.
  EXPECT_UNSUPPORTED(
      IsAudioEncryptionSchemeSupported(kExternalClearKey, "Invalid"));
  EXPECT_UNSUPPORTED(
      IsVideoEncryptionSchemeSupported(kExternalClearKey, "Invalid"));
  EXPECT_UNSUPPORTED(IsAudioEncryptionSchemeSupported(kExternalClearKey, ""));
  EXPECT_UNSUPPORTED(IsVideoEncryptionSchemeSupported(kExternalClearKey, ""));
}

// External Clear Key is disabled by default.
IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesExternalClearKeyNotEnabledTest,
    Basic) {
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, video_webm_codecs()));

  // Clear Key should still be registered.
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        video_webm_codecs()));
}

//
// Widevine
//

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Basic) {
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                   video_webm_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                   audio_webm_codecs()));
  EXPECT_WV(
      IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType, opus_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                   audio_mp4_flac_codecs()));
  EXPECT_WV_PROPRIETARY(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, video_mp4_codecs()));
  EXPECT_WV_PROPRIETARY(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, audio_mp4_codecs()));
  EXPECT_WV(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, opus_codecs()));

  // Without hardware support, HEVC is not supported.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                            video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest,
                       InvalidKeySystems) {
  // Case sensitive.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "com.widevine.WideVine", kVideoWebMMimeType, video_webm_codecs()));

  // TLDs are not allowed.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("com.", kVideoWebMMimeType, video_webm_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem("com", kVideoWebMMimeType, video_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("com.widevine.", kVideoWebMMimeType,
                                            video_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem("com.widevine", kVideoWebMMimeType,
                                            video_webm_codecs()));

  // Incomplete.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "com.widevine.alp", kVideoWebMMimeType, video_webm_codecs()));

  // Extra character.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "com.widevine.alphab", kVideoWebMMimeType, video_webm_codecs()));

  // There are no child key systems for Widevine.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      "com.widevine.alpha.child", kVideoWebMMimeType, video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, NoCodecs) {
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType, no_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType, no_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, no_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, no_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Video_WebM) {
  // Valid video types.
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                   video_webm_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                   vp9_profile0_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                   vp9_profile2_codecs()));
  EXPECT_WV_AV1(
      IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType, av1_codecs()));

  // Non-video WebM codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                            audio_webm_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType, opus_codecs()));

  // Invalid or non-Webm codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                            audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                            audio_mp4_flac_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                            video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                            video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Audio_WebM) {
  // Valid audio types.
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                   audio_webm_codecs()));
  EXPECT_WV(
      IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType, opus_codecs()));

  // Non-audio WebM codecs.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            video_webm_codecs()));

  // Invalid or non-Webm codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            audio_mp4_flac_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            video_mp4_hevc_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Video_MP4) {
  // Valid video types.
  EXPECT_WV_PROPRIETARY(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, video_mp4_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                   vp9_profile0_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                   vp9_profile2_codecs()));
  EXPECT_WV_AV1(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, av1_codecs()));

  // High 10-bit Profile is not supported when using Widevine.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                            video_mp4_hi10p_codecs()));

  // HEVC is not supported when using Widevine.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                            video_mp4_hevc_codecs()));

  // Non-video MP4 codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, audio_mp4_codecs()));
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, opus_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                            audio_mp4_flac_codecs()));

  // Invalid or non-MP4 codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                            audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                            video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Audio_MP4) {
  // Valid audio types.
  EXPECT_WV_PROPRIETARY(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, audio_mp4_codecs()));
  EXPECT_WV(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, opus_codecs()));
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                   audio_mp4_flac_codecs()));

  // Non-audio MP4 codecs.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, video_mp4_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                            video_mp4_hevc_codecs()));

  // Invalid or Non-MP4 codec.
  EXPECT_UNSUPPORTED(
      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, invalid_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                            audio_webm_codecs()));
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                            video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, SessionType) {
  // Temporary session always supported.
  EXPECT_WV(IsSessionTypeSupported(kWidevine, SessionType::kTemporary));

  // Persistent license session support varies by platform.
  auto result =
      IsSessionTypeSupported(kWidevine, SessionType::kPersistentLicense);

#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
  // Persistent license session supported by Widevine key system on Windows and
  // Mac. On ChromeOS, it is supported when the protected media identifier
  // permission is allowed. See kUnsafelyAllowProtectedMediaIdentifierForDomain
  // used above.
  EXPECT_WV(result);
#else
  EXPECT_UNSUPPORTED(result);
#endif
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Robustness) {
  // Robustness is recommended but not required.
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, nullptr));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, ""));

  EXPECT_UNSUPPORTED(IsVideoRobustnessSupported(kWidevine, "Invalid String"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));

#if BUILDFLAG(IS_CHROMEOS_ASH)
  // "HW_SECURE_ALL" supported on ChromeOS when the protected media identifier
  // permission is allowed. See kUnsafelyAllowProtectedMediaIdentifierForDomain
  // used above.
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#else
  EXPECT_UNSUPPORTED(IsVideoRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#endif

  // Robustness is recommended but not required.
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, nullptr));
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, ""));

  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kWidevine, "Invalid String"));
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));

#if BUILDFLAG(IS_CHROMEOS_ASH)
  // "SW_SECURE_DECODE" and "HW_SECURE_ALL" supported on ChromeOS when the
  // protected media identifier permission is allowed. See
  // kUnsafelyAllowProtectedMediaIdentifierForDomain used above.
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#else
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#endif
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest,
                       EncryptionScheme) {
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, nullptr));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cenc"));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs"));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs-1-9"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, nullptr));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cenc"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cbcs"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cbcs-1-9"));

  // Invalid encryption schemes will be rejected.
  EXPECT_UNSUPPORTED(IsAudioEncryptionSchemeSupported(kWidevine, "Invalid"));
  EXPECT_UNSUPPORTED(IsVideoEncryptionSchemeSupported(kWidevine, "Invalid"));
  EXPECT_UNSUPPORTED(IsAudioEncryptionSchemeSupported(kWidevine, ""));
  EXPECT_UNSUPPORTED(IsVideoEncryptionSchemeSupported(kWidevine, ""));
}

//
// EncryptedMediaSupportedTypesWidevineHwSecureTest tests Widevine with hardware
// secure decryption support.
// - ChromeOS: HW_SECURE_ALL are supported by default which is not affected by
// feature media::kHardwareSecureDecryption.
// - Linux/Mac/Windows: Feature media::kHardwareSecureDecryption is enabled, and
// command line switch kOverrideHardwareSecureCodecsForTesting is used to always
// enable vp8 and vp9, and disable avc1; always enable 'cenc' and disable
// 'cbcs'/'cbcs-1-9', for HW_SECURE* robustness levels. With the switch, real
// hardware capabilities are not checked for the stability of tests.

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       Robustness) {
  // Robustness is recommended but not required.
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, nullptr));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, ""));

  // Video robustness.
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "HW_SECURE_ALL"));

  // Audio robustness.
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
#if BUILDFLAG(IS_CHROMEOS_ASH)
  // "SW_SECURE_DECODE" and "HW_SECURE_ALL" supported on ChromeOS when the
  // protected media identifier permission is allowed. See
  // kUnsafelyAllowProtectedMediaIdentifierForDomain used above.
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#else
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#endif

  // Video proprietary codecs.
  EXPECT_WV_PROPRIETARY(
      IsVideoMp4RobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));
  EXPECT_WV_PROPRIETARY(
      IsVideoMp4RobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
#if BUILDFLAG(IS_CHROMEOS_ASH)
  // "SW_SECURE_DECODE" and "HW_SECURE_ALL" supported on ChromeOS when the
  // protected media identifier permission is allowed. See
  // kUnsafelyAllowProtectedMediaIdentifierForDomain used above.
  EXPECT_WV_PROPRIETARY(
      IsVideoMp4RobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_WV_PROPRIETARY(
      IsVideoMp4RobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#else
  // Not supported because hardware secure avc1 is not supported.
  EXPECT_UNSUPPORTED(
      IsVideoMp4RobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(IsVideoMp4RobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#endif

  // HEVC codecs. Not supported because either HEVC not supported
  // (BUILDFLAG(ENABLE_PLATFORM_HEVC)) or HEVC not specified in
  // kOverrideHardwareSecureCodecsForTesting.
  // TODO(b/187242911): Add HEVC to kOverrideHardwareSecureCodecsForTesting.
  EXPECT_UNSUPPORTED(
      IsVideoMp4HevcRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsVideoMp4HevcRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_UNSUPPORTED(
      IsVideoMp4HevcRobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsVideoMp4HevcRobustnessSupported(kWidevine, "HW_SECURE_ALL"));

  // Audio proprietary codecs.
  // "SW_SECURE_CRYPTO" is always supported.
  EXPECT_WV_PROPRIETARY(
      IsAudioMp4RobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));
#if BUILDFLAG(IS_CHROMEOS_ASH)
  // "SW_SECURE_DECODE", "HW_SECURE_CRYPTO", and "HW_SECURE_ALL" supported
  // on ChromeOS when the protected media identifier permission is allowed.
  // See kUnsafelyAllowProtectedMediaIdentifierForDomain used above.
  EXPECT_WV_PROPRIETARY(
      IsAudioMp4RobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_WV_PROPRIETARY(
      IsAudioMp4RobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_WV_PROPRIETARY(
      IsAudioMp4RobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#else
  // Test only enables audio codec Vorbis, so MP4 not supported.
  EXPECT_UNSUPPORTED(
      IsAudioMp4RobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_UNSUPPORTED(
      IsAudioMp4RobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(IsAudioMp4RobustnessSupported(kWidevine, "HW_SECURE_ALL"));
#endif
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       EncryptionScheme) {
  // Both encryption schemes are supported when no robustness is specified.
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cenc"));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs"));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs-1-9"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cenc"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cbcs"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cbcs-1-9"));

  // Both encryption schemes are supported when SW_SECURE* robustness is
  // specified.
  EXPECT_WV(
      IsAudioEncryptionSchemeSupported(kWidevine, "cenc", "SW_SECURE_CRYPTO"));
  EXPECT_WV(
      IsAudioEncryptionSchemeSupported(kWidevine, "cbcs", "SW_SECURE_CRYPTO"));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs-1-9",
                                             "SW_SECURE_CRYPTO"));
  EXPECT_WV(
      IsVideoEncryptionSchemeSupported(kWidevine, "cenc", "SW_SECURE_DECODE"));
  EXPECT_WV(
      IsVideoEncryptionSchemeSupported(kWidevine, "cbcs", "SW_SECURE_DECODE"));
  EXPECT_WV(IsVideoEncryptionSchemeSupported(kWidevine, "cbcs-1-9",
                                             "SW_SECURE_DECODE"));

  // For HW_SECURE* robustness levels, 'cenc' is always supported by setting
  // the command line switch kOverrideHardwareSecureCodecsForTesting.
  // ChromeOS has special handling for hardware support, so 'cbcs' is supported
  // on ChromeOS, but not on other platforms.
  EXPECT_WV(
      IsAudioEncryptionSchemeSupported(kWidevine, "cenc", "HW_SECURE_CRYPTO"));
  EXPECT_WV(
      IsVideoEncryptionSchemeSupported(kWidevine, "cenc", "HW_SECURE_ALL"));
#if BUILDFLAG(IS_CHROMEOS_ASH)
  EXPECT_WV(
      IsAudioEncryptionSchemeSupported(kWidevine, "cbcs", "HW_SECURE_CRYPTO"));
  EXPECT_WV(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs-1-9",
                                             "HW_SECURE_CRYPTO"));
  EXPECT_WV(
      IsVideoEncryptionSchemeSupported(kWidevine, "cbcs", "HW_SECURE_ALL"));
  EXPECT_WV(
      IsVideoEncryptionSchemeSupported(kWidevine, "cbcs-1-9", "HW_SECURE_ALL"));
#else
  EXPECT_UNSUPPORTED(
      IsAudioEncryptionSchemeSupported(kWidevine, "cbcs", "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(IsAudioEncryptionSchemeSupported(kWidevine, "cbcs-1-9",
                                                      "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsVideoEncryptionSchemeSupported(kWidevine, "cbcs", "HW_SECURE_ALL"));
  EXPECT_UNSUPPORTED(
      IsVideoEncryptionSchemeSupported(kWidevine, "cbcs-1-9", "HW_SECURE_ALL"));
#endif
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       WidevineExperiment) {
  EXPECT_UNSUPPORTED(
      IsVideoRobustnessSupported(kWidevineExperiment, "SW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsVideoRobustnessSupported(kWidevineExperiment, "SW_SECURE_DECODE"));
  EXPECT_UNSUPPORTED(
      IsVideoRobustnessSupported(kWidevineExperiment, "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsVideoRobustnessSupported(kWidevineExperiment, "HW_SECURE_ALL"));
  EXPECT_UNSUPPORTED(
      IsAudioRobustnessSupported(kWidevineExperiment, "SW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(
      IsAudioRobustnessSupported(kWidevineExperiment, "HW_SECURE_CRYPTO"));
}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesWidevineHwSecureExperimentTest,
    Robustness) {
  // Widevine software security should always be supported.
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevine, "SW_SECURE_DECODE"));
  EXPECT_WV(IsAudioRobustnessSupported(kWidevine, "SW_SECURE_CRYPTO"));

  // Widevine experiment key system is only supported on Windows.
#if BUILDFLAG(IS_WIN)
  // Widevine key system doesn't support hardware security.
  EXPECT_UNSUPPORTED(IsVideoRobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));
  EXPECT_UNSUPPORTED(IsVideoRobustnessSupported(kWidevine, "HW_SECURE_ALL"));
  EXPECT_UNSUPPORTED(IsAudioRobustnessSupported(kWidevine, "HW_SECURE_CRYPTO"));

  // Widevine experiment key system supports both software/hardware security.
  EXPECT_WV(
      IsVideoRobustnessSupported(kWidevineExperiment, "SW_SECURE_CRYPTO"));
  EXPECT_WV(
      IsVideoRobustnessSupported(kWidevineExperiment, "SW_SECURE_DECODE"));
  EXPECT_WV(
      IsVideoRobustnessSupported(kWidevineExperiment, "HW_SECURE_CRYPTO"));
  EXPECT_WV(IsVideoRobustnessSupported(kWidevineExperiment, "HW_SECURE_ALL"));
  EXPECT_WV(
      IsAudioRobustnessSupported(kWidevineExperiment, "SW_SECURE_CRYPTO"));
  EXPECT_WV(
      IsAudioRobustnessSupported(kWidevineExperiment, "HW_SECURE_CRYPTO"));
#else
  EXPECT_UNSUPPORTED(
      IsAudioRobustnessSupported(kWidevineExperiment, "SW_SECURE_DECODE"));
  EXPECT_UNSUPPORTED(
      IsAudioRobustnessSupported(kWidevineExperiment, "HW_SECURE_ALL"));
#endif
}

//
// Misc failure test cases.
//

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesTest,
                       ClearKeyCdmNotRegistered) {
  // External Clear Key will not be supported because Clear Key CDM is not
  // registered on the command line.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, video_webm_codecs()));

  // Clear Key should always be supported.
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        video_webm_codecs()));
}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest,
    Basic) {
  // External Clear Key will not be supported because Clear Key CDM is
  // registered with the wrong path.
  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
      kExternalClearKey, kVideoWebMMimeType, video_webm_codecs()));

  // Clear Key should always be supported.
  EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                        video_webm_codecs()));
}

#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
